package com.sky.service.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.SalesTop10ReportVO;
import com.sky.vo.TurnoverReportVO;
import com.sky.vo.UserReportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserMapper userMapper;
    /**
     * 根据时间区间 进行营业额统计
     * @param begin  开始时间  2023-09-01
     * @param end   结束时间   2023-09-10
     * @return
     */
    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
        // service 做什么呢？
        log.info("营业额统计...前端要什么 我们就封装什么");
        // do 1 时间区间 以字符串形式 之间,隔开
        // 1.1 定义存储 时间区间 的集合
        List<LocalDate> dateList = new ArrayList<>();
        //1.2 循环 遍历 区间每一天对象 存到 集合中
        dateList.add(begin);
        while (!begin.equals(end)){//不进行添加了
                        begin = begin.plusDays(1);//往后加一天
                        dateList.add(begin);
        }
        //1.3 dateList 存了每一天日期对象  要的结果是字符串
        String dateListStr = StringUtils.join(dateList,",");
        // do 2  求出每一天的 营业额 存到 营业额集合中  把集合变成字符串
        // 2.1 定义存储 每日营业额的集合
        List<Double> turnoverList= new ArrayList<>();
        // 2.2 遍历出需要查询的指定天  2023-09-01  2023-09-02
        for (LocalDate localDate : dateList) {
            int status= Orders.COMPLETED;
            LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MAX);
            LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MIN);
            Double turnover=orderMapper.sumByDay(status,beginTime,endTime);
            turnover = turnover==null?0.0:turnover;//如果当天没有营业额就是0
            turnoverList.add(turnover);// turnover营业额
        }
        // 2.4 把集合变成字符串
        String turnoverListStr = StringUtils.join(turnoverList, ",");

        TurnoverReportVO reportVO = new TurnoverReportVO();

        reportVO.setDateList(dateListStr);
        reportVO.setTurnoverList(turnoverListStr);
        return reportVO;


    }

    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        log.info("用户统计...前端要什么 我们就封装什么");
        // do 1 时间区间 以字符串形式 之间,隔开
        // 1.1 定义存储 时间区间 的集合
        List<LocalDate> dateList= new ArrayList<>();
        //1.2 循环 遍历 区间每一天对象 存到 集合中
        dateList.add(begin);
        while (!begin.equals(end)){//不进行添加了
            begin = begin.plusDays(1);//往后加一天
            dateList.add(begin);
        }
        //1.3 dateList 存了每一天日期对象  要的结果是字符串
        String dateListStr = StringUtils.join(dateList, ",");
        // 2.1  定义 一个存储 每日新增用户数量的集合
        List<Integer> newUserList= new ArrayList<>();
        // 2.2  定义 每日用户总量 列表集合
        List<Integer> totalUserList = new ArrayList<>();
        for (LocalDate localDate : dateList) {
            // 2.3 查询数据库 查询中指定天的 新增用户数存到 集合中
            // localDate 需要查询的每一天
            LocalDateTime beginTime = LocalDateTime.of(localDate,LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(localDate,LocalTime.MAX);
            Map map = new HashMap();
            map.put("beginTime",beginTime);
            map.put("endTime",endTime);
            Integer newUser = userMapper.countByMap(map);
            newUserList.add(newUser);

            //  2.4 查询数据库 查询中 截止到指定天的 用户总数存到 集合中
            Map map1 = new HashMap();
            map1.put("endTime",endTime);
            Integer totalUser = userMapper.countByMap(map1);
            totalUserList.add(totalUser);
        }

        String newUserListStr = StringUtils.join(newUserList,",");
        String totalUserListStr = StringUtils.join(totalUserList,",");
        //前端要什么 我们给什么
        UserReportVO userReportVO = new UserReportVO();
        userReportVO.setDateList(dateListStr);
        userReportVO.setNewUserList(newUserListStr);
        userReportVO.setTotalUserList(totalUserListStr);

        return userReportVO;
    }
    /**
     * 订单统计
     *      日期列表
     *      每日订单数
     *      每日有效订单数
     *      区间时间的订单总数
     *      区间时间的有效订单数
     *      区间时间的完成率
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO getOrdersStatistics(LocalDate begin, LocalDate end) {
        log.info("用户统计...前端要什么 我们就封装什么");
        // do 1 时间区间 以字符串形式 之间,隔开
        // 1.1 定义存储 时间区间 的集合
        List<LocalDate> dateList= new ArrayList<>();
        //1.2 循环 遍历 区间每一天对象 存到 集合中
        dateList.add(begin);
        while (!begin.equals(end)){//不进行添加了
            begin = begin.plusDays(1);//往后加一天
            dateList.add(begin);
        }
        //1.3 dateList 存了每一天日期对象  要的结果是字符串
        String dateListStr = StringUtils.join(dateList, ",");
        // 2.1  定义存储每日订单数的集合
        ////        每日有效订单数---集合--string
        List<Integer> orderCountList= new ArrayList<>();
        // 2.2  定义 每日用户总量 列表集合
        List<Integer> validOrderCountList = new ArrayList<>();
        //   3.1 定义接收区间时间的订单总数的 数值
        Integer totalOrderCount = 0;
        //   3.2 定义接收区间时间的有效订单总数的 数值
        Integer validOrderCount = 0;
        for (LocalDate localDate : dateList) {
            // 2.3 查询数据库 查询中指定天的 新增用户数存到 集合中
            // localDate 需要查询的每一天
            LocalDateTime beginTime = LocalDateTime.of(localDate,LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(localDate,LocalTime.MAX);
            // 2.3 查询数据库 查询中指定天的 新增用户数存到 集合中
            // localDate 需要查询的每一天
            Map map = new HashMap();
            map.put("beginTime",beginTime);
            map.put("endTime",endTime);
            Integer orderCount = orderMapper.countByMap(map);//当天订单总数
           totalOrderCount +=orderCount;
           orderCountList.add(orderCount);
            // 2.5 查询每天的有效订单数  存到集合中

            //  2.4 查询数据库 查询中 截止到指定天的 用户总数存到 集合中
            Map map1 = new HashMap();
            map1.put("status",Orders.COMPLETED);//设置有效条件 已完成
            map1.put("beginTIme",beginTime);
            map1.put("endTime",endTime);
            Integer validCount = orderMapper.countByMap(map1);//当前有效订单数
            validOrderCount += validCount;// 求每天的订单数的和
            validOrderCountList.add(validCount);
        }

        String orderCountListStr = StringUtils.join(orderCountList,",");
        String validOrderCountListStr = StringUtils.join(validOrderCountList,",");

//         区间时间的完成率
        //订单完成率
        Double orderCompletionRate = 0.0;//默认完成率是0.0
        //  有效订单数/订单总数   订单总数是0 不能玩
        if (totalOrderCount != 0){//有订单
            orderCompletionRate = validOrderCount.doubleValue()/totalOrderCount;
        }
        //以终为始
        OrderReportVO orderReportVO = new OrderReportVO();
        orderReportVO.setDateList(dateListStr);//日期列表
        orderReportVO.setOrderCountList(orderCountListStr);//每日订单数
        orderReportVO.setValidOrderCountList(validOrderCountListStr);//每日有效订单数
        orderReportVO.setTotalOrderCount(totalOrderCount);//区间订单总数
        orderReportVO.setValidOrderCount(validOrderCount);//区间有效订单总数
        orderReportVO.setOrderCompletionRate(orderCompletionRate);//订单完成率

        return orderReportVO;
    }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        //查询销量开始 时间
        LocalDateTime beginTime = LocalDateTime.of(begin,LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end,LocalTime.MAX);

        List<GoodsSalesDTO> goodsSalesDTOList = orderMapper.getSalesTop10(beginTime,endTime);
        // 一个个对象
        // 定义 一个接收 菜品名称的 集合
        List<String> nameList = new ArrayList<>();
        // 定义 一个接收 菜品销量 的 集合
        List<Integer> numberList = new ArrayList<>();

        if(goodsSalesDTOList!=null && goodsSalesDTOList.size()>0){
            for (GoodsSalesDTO goodsSalesDTO : goodsSalesDTOList) {
                //            name 口水鱼   number 2
                nameList.add(goodsSalesDTO.getName());//获取商品名称存到商品名称集合
                numberList.add(goodsSalesDTO.getNumber());//获取商品销量 存到商品销量集合
            }
        }
        // 将集合转换成字符串
        String nameListStr = StringUtils.join(nameList,",");
        String numberListStr = StringUtils.join(numberList,",");

        //以终为始
        SalesTop10ReportVO reportVO = new SalesTop10ReportVO();
        reportVO.setNameList(nameListStr);//前十的 菜品/套餐 名字
        reportVO.setNumberList(numberListStr);//前10 菜品/套餐 销量
        return reportVO;
    }

}
